import * as PIXI from "pixi.js";

export default function () {
  let app;
  const pixiMap = {
    pointNormalSize: 0.5, //  点大小
    pointActiveSize: 0.8, //  高亮点大小
    pointNormalColor: "0x9370DB", //  点颜色
    pointActiveColor: "0xFF6666", //  高亮点颜色
    pointAlpha: 0.66, //  点透明度
    lineSingleSize: 0.05, //  单向线宽度
    lineDoubleSize: 0.05, //  双向线宽度
    lineSingleColor: "0x1B9AF7", //  单向线颜色
    lineDoubleColor: "0x1B9AF7", //  双向线颜色
    lineSingleAlpha: 0.25, //  单向线透明度
    lineDoubleAlpha: 1, //  双向线透明度
    polygonSize: 0.05, // 绘制虚拟墙的宽度
    polygonColor: "0xFF0000", // 绘制虚拟墙的颜色
    scanColor: "0x6600FF", // 激光雷达的颜色
    viewLocking: false, //  视角是否锁定
    stageMove: false, //  舞台是否可移动
    pointNameShow: false, //  点位名称是否常显
    polygonNameShow: true, //  安全区名称是否常显
    clickPoint: (p) => {
      console.log(p.id + "点位被点击");
    }, //  点位的点击事件
    clickPolygon: (p) => {
      console.log(p.id + "安全区被点击");
    }, //  点位的点击事件
    clickPolygonDot: (p) => {
      console.log(p.id + "安全区点被点击");
    }, //  点位的点击事件
    stagePointermove: (e) => {},
    xMax: 1, //  水平方向限制区间的最大占比
    xMin: 1, //  水平方向限制区间的最小占比
    yMax: 1, //  垂直方向限制区间的最大占比
    yMin: 1, //  垂直方向限制区间的最小占比
  };

  /**
   * 创建舞台
   * @param div canvas的父类div
   * @returns {PIXI.Container|number|null|*} pixijs的舞台元素，即根级父类容器
   */
  pixiMap.createStage = (div) => {
    if (!div) return null;
    const width = div.offsetWidth;
    const height = div.offsetHeight;
    app = new PIXI.Application({
      width,
      height,
      antialias: true,
      resizeTo: div,
    });
    // 渲染canvas
    div.appendChild(app.view);
    // 改变Y轴中心
    app.stage.y = height;
    // 启用事件
    app.stage.eventMode = "static";
    let startPointX, startPointY;
    app.stage.onpointerdown = (e) => {
      const timeInterval = new Date().getTime();
      // 视角未锁定，记录点击位置，用于拖动镜头
      if (!pixiMap.viewLocking) {
        pixiMap.stageMove = true;
        startPointX = app.stage.x - e.data.global.x;
        startPointY = app.stage.y - e.data.global.y;
      }
      // 获取安全区点信息
      if (pixiMap.polygonState) {
        pixiMap.clickDot(e);
      }
      // 获取点位位置和点位方向数据
      if (pixiMap.poseState) {
        if (pixiMap.lastClick) {
          if (timeInterval - pixiMap.lastClick < 500) {
            // 双击时间小于500毫秒 触发
            pixiMap.clickPose(e);
          }
        }
        pixiMap.lastClick = timeInterval;
      }
      // 机器人重定位开启中
      if (pixiMap.changeLocation) {
        if (pixiMap.lastClick1) {
          if (timeInterval - pixiMap.lastClick1 < 500) {
            // 双击时间小于500毫秒 触发
            pixiMap.changePose(
              pixiMap.globalToRos(e.data.global.x, e.data.global.y)
            );
          }
        }
        pixiMap.lastClick1 = timeInterval;
      }
      // 机器人重定方向开启中
      if (pixiMap.changeDirection) {
        pixiMap.changeTheta(
          pixiMap.globalToRos(e.data.global.x, e.data.global.y)
        );
      }
    };
    app.stage.onpointerup = () => {
      pixiMap.stageMove = false;
    };
    app.stage.onpointermove = (e) => {
      if (pixiMap.stageMoveState) {
        pixiMap.stagePointermove(e);
      } else {
        // 判断鼠标是否超出画布范围
        if (
          e.data.global.y > 0 &&
          e.data.global.y < div.offsetHeight &&
          e.data.global.x > 0 &&
          e.data.global.x < div.offsetWidth
        ) {
          // 判断地图是否允许拖动
          if (pixiMap.stageMove) {
            const x = e.data.global.x + startPointX;
            // 三元判断为限制水平方向露出黑边的区间
            app.stage.x =
              x >= app.stage.width * pixiMap.xMax
                ? app.stage.width * pixiMap.xMax
                : x <= div.offsetWidth - app.stage.width * pixiMap.xMin
                ? div.offsetWidth - app.stage.width * pixiMap.xMin
                : x;
            const y = e.data.global.y + startPointY;
            // 三元判断为限制垂直方向露出黑边的区间
            app.stage.y =
              y >= app.stage.height * pixiMap.yMax
                ? app.stage.height * pixiMap.yMax
                : y <= div.offsetHeight - app.stage.height * pixiMap.yMin
                ? div.offsetHeight - app.stage.height * pixiMap.yMin
                : y;
          }
        } else {
          pixiMap.stageMove = false;
        }
      }
    };
    app.stage.onwheel = (e) => {
      pixiMap.zoom(e.deltaY);
    };
    div.addEventListener(
      "touchstart",
      function (e) {
        const evt = e || window.event; // 考虑兼容性
        // 双指触摸时
        if (evt.touches.length === 2) {
          // 地图拖动关闭
          pixiMap.stageMove = false;
          // 记录首次双指距离
          pixiMap.distance = getDistance(evt.touches[0], evt.touches[1]);
          // 记录首次双指中心
          pixiMap.centerPos = {
            x: (evt.touches[0].clientX + evt.touches[1].clientX) / 2,
            y: (evt.touches[0].clientY + evt.touches[1].clientY) / 2,
          };
        }
      },
      {
        passive: false,
      }
    );

    div.addEventListener(
      "touchmove",
      function (e) {
        const evt = e || window.event; // 考虑兼容性
        if (evt.touches.length === 2) {
          pixiMap.stageMove = false;
          // 判断距离是否需要重新计算距离
          if (pixiMap.distance === 0) {
            pixiMap.distance = getDistance(evt.touches[0], evt.touches[1]);
          }
          // 判断2个点之间距离-第一次点距离是否大于等于10
          if (
            getDistance(evt.touches[0], evt.touches[1]) - pixiMap.distance >
            10
          ) {
            // 对中心点放大
            pixiMap.zoom(0.5, pixiMap.centerPos.x, pixiMap.centerPos.y);
            // 触发放大后重新计算双指滑动距离
            pixiMap.distance = 0;
          } else if (
            pixiMap.distance - getDistance(evt.touches[0], evt.touches[1]) >
            10
          ) {
            // 对中心点缩小
            pixiMap.zoom(-0.5, pixiMap.centerPos.x, pixiMap.centerPos.y);
            // 触发缩小后重新计算双指滑动距离
            pixiMap.distance = 0;
          }
        }
      },
      {
        passive: false,
      }
    );
    pixiMap.initStage();
    return app.stage;
  };

  /**
   * 触发场景外事件
   */
  pixiMap.outStage = () => {
    pixiMap.stageMove = false;
  };

  /**
   * 销毁舞台
   */
  pixiMap.destroyStage = () => {
    app.stage.children.forEach((item) => {
      if (item.isSprite) {
        item.destroy();
      } else {
        item.destroy(true);
      }
    });
    app.destroy(true, true);
  };

  /**
   * 初始化所有对象
   */
  pixiMap.initStage = () => {
    pixiMap.map = new PIXI.Sprite(); //  地图
    pixiMap.lineContainer = new PIXI.Container(); //  存放线的容器
    pixiMap.polygonContainer = new PIXI.Container(); //  存放安全区的容器
    pixiMap.pointContainer = new PIXI.Container(); //  存放点的容器
    pixiMap.robot = new PIXI.Sprite(); //  机器人
    pixiMap.scanContainer = new PIXI.Container(); //  存放激光雷达的容器
  };

  /**
   * 展示舞台内所有元素
   * 将舞台居中进行适配放大
   * 展示地图、机器人及路线
   */
  pixiMap.updateStage = () => {
    if (!pixiMap.div) return;
    let W = 10;
    let H = 10;
    if (pixiMap.div.height > pixiMap.div.width) {
      H = (W * pixiMap.div.offsetHeight) / pixiMap.div.offsetWidth;
    } else {
      W = (H * pixiMap.div.offsetWidth) / pixiMap.div.offsetHeight;
    }
    app.stage.scale.set(
      pixiMap.div.offsetWidth / W,
      pixiMap.div.offsetHeight / H
    );
    shiftStage(-W / 2, -H / 2);
    pixiMap.stage.removeChildren();
    pixiMap.stage.addChild(pixiMap.map);
    pixiMap.stage.addChild(pixiMap.lineContainer);
    pixiMap.stage.addChild(pixiMap.polygonContainer);
    pixiMap.stage.addChild(pixiMap.pointContainer);
    pixiMap.stage.addChild(pixiMap.robot);
    pixiMap.stage.addChild(pixiMap.scanContainer);
  };

  /**
   * 创建地图
   * @param options ：
   *    * img - 地图图片
   *    * resolution  - 像素比 单位：像素/米
   *    * x - 地图水平方向偏移量
   *    * y - 地图垂直方向偏移量
   * @returns {*} 地图对象，pixijs的精灵
   * @constructor
   */
  pixiMap.createMap = (options) => {
    if (!options.img) return null;
    const img = options.img;
    const resolution = options.resolution || 0.025;
    const x = options.x || -20;
    const y = options.y || -20;
    pixiMap.map = PIXI.Sprite.from(img);
    // 改变Y轴中心
    pixiMap.map.y = -pixiMap.map.height * resolution;
    // 按像素比每米进行缩小画布
    pixiMap.map.scale.set(resolution);

    // 设置位置
    pixiMap.map.x += x;
    pixiMap.map.y -= y;
    // 设置区间系数
    pixiMap.xMax = (-options.x / pixiMap.map.width).toFixed(4);
    pixiMap.xMin = (1 + options.x / pixiMap.map.width).toFixed(4);
    pixiMap.yMax = (1 + options.y / pixiMap.map.height).toFixed(4);
    pixiMap.yMin = (-options.y / pixiMap.map.height).toFixed(4);
    // 清理地图缓存
    PIXI.utils.clearTextureCache();
    return pixiMap.map;
  };

  /**
   * 创建机器人
   *    * img - 素材图片
   *    * size - 大小
   *    * color - 颜色
   *    * alpha - 透明度
   * @returns {Sprite|null} 机器人对象，pixijs的精灵
   * @param options
   */
  pixiMap.createRobot = (options) => {
    if (!options.img) return null;
    const img = options.img;
    const size = options.size || 1;
    const color = options.color || "0x1E90FF";
    const alpha = options.alpha || 1;
    const robot = PIXI.Sprite.from(img);
    const scale = size / img.width;
    robot.alpha = alpha;
    robot.scale.set(scale);
    robot.anchor.set(0.5); // 图片中心为原点，而不是左上角
    robot.tint = color;
    return robot;
  };

  /**
   * 视角锁定（聚焦机器人位置）
   */
  pixiMap.focus = () => {
    pixiMap.stage.x = pixiMap.div.offsetWidth / 2;
    pixiMap.stage.y = pixiMap.div.offsetHeight / 2;
    shiftStage(pixiMap.robot.x, -pixiMap.robot.y);
  };

  /**
   * 更新机器人位置
   * @param pos 机器人ros点位
   */
  pixiMap.updateRobot = (pos) => {
    pixiMap.robot.x = pos.position.x;
    pixiMap.robot.y = -pos.position.y;
    // pixijs用的是弧度制，角度转弧度
    pixiMap.robot.rotation =
      ((90 + pixiMap.toTheta(pos.orientation)) * Math.PI) / 180;
    if (pixiMap.viewLocking) {
      // 视角锁定
      pixiMap.focus();
    }
  };

  /**
   *  设置点位样式
   * @param options
   *      * img 素材
   *      * size  大小
   *      * color 颜色
   *      * activeColor 高亮颜色
   *      * alpha 透明度
   */
  pixiMap.setPointStyle = (options) => {
    if (options.img) pixiMap.poseImg = options.img;
    if (options.size) pixiMap.pointSize = options.size;
    if (options.color) pixiMap.pointNormalColor = options.color;
    if (options.activeColor) pixiMap.pointActiveColor = options.activeColor;
    if (options.alpha) pixiMap.pointAlpha = options.alpha;
  };

  /**
   * 清空路线
   */
  pixiMap.clearRail = () => {
    pixiMap.pointContainer.removeChildren();
    pixiMap.lineContainer.removeChildren();
  };

  /**
   * 画路线
   * @param list 点位列表
   */
  pixiMap.drawRail = (list) => {
    //  得有点位图片
    if (!pixiMap.poseImg) return;
    // savedList为最近一次的list，当函数传参为空是即画最近一次的路线
    if (list) pixiMap.savedList = JSON.parse(JSON.stringify(list));
    if (!pixiMap.savedList) return;
    pixiMap.clearRail();
    const m = new Map();
    pixiMap.savedList.forEach((v, n) => {
      v.index = n;
      m.set(v.id, v);
    });
    pixiMap.savedList.forEach((point, index) => {
      if (pixiMap.highlightId === point.id) {
        pixiMap.pointSize = pixiMap.pointActiveSize;
        pixiMap.pointColor = pixiMap.pointActiveColor;
      } else {
        pixiMap.pointSize = pixiMap.pointNormalSize;
        pixiMap.pointColor = pixiMap.pointNormalColor;
      }
      pixiMap.pointContainer.addChild(createPoint(point));
      point.connectedPose = point.connectedPose || [];
      point.connectedPose.forEach((p) => {
        if (!m.get(p)) return; // 连接点中的跨地图点直接return，不进行连线
        //  将两个点的下标组合成ID，如点3和点4的连接，3-4
        const lineId = index + 1 + "-" + (m.get(p).index + 1);
        //  查找是否已存在连线，用反向ID去查询，如4-3
        const antherLine = pixiMap.getLine(
          m.get(p).index + 1 + "-" + (index + 1)
        );
        // console.log('hhh', antherLine)
        if (antherLine) {
          //  查到已存在一条连接线，进行编辑，若未查询到，则进行创建
          pixiMap.editLine(
            antherLine,
            point.pose.position,
            m.get(p).pose.position,
            true
          );
        } else {
          const line = createLine(point.pose.position, m.get(p).pose.position);
          line.name = lineId;
          pixiMap.lineContainer.addChild(line);
        }
      });
    });
  };

  /**
   * 点位显示高亮
   * @param id 高亮点位id
   */
  pixiMap.highlight = (id) => {
    pixiMap.highlightId = id;
    pixiMap.drawRail();
  };

  /**
   * 创建点
   * @param p 点对象
   * @returns {Sprite} 点对象（pixijs的精灵）
   */
  function createPoint(p) {
    const pos = p.pose || p;
    // 点对象
    const point = new PIXI.Container();
    //  点素材
    const pose = PIXI.Sprite.from(pixiMap.poseImg);
    //  点名称
    const pointText = new PIXI.Text(p.name);
    point.addChild(pose);
    point.addChild(pointText);
    // 点素材参数
    pose.anchor.set(0.5);
    pose.tint = pixiMap.pointColor;
    pose.alpha = pixiMap.pointAlpha;
    pose.rotation = ((90 + pixiMap.toTheta(pos.orientation)) * Math.PI) / 180;
    pose.scale.set(pixiMap.pointSize / pixiMap.pointNormalSize);
    //  点名称参数
    pointText.anchor.set(0.5);
    pointText.y = -pixiMap.poseImg.height;
    pointText.visible = pixiMap.pointNameShow;
    //  点位整体参数
    point.scale.set(pixiMap.pointNormalSize / pixiMap.poseImg.width);
    point.x = pos.position.x;
    point.y = -pos.position.y;
    point.name = p.id;
    // -----------事件分割线-------------
    pose.eventMode = "static";
    pose.onpointerenter = () => {
      if (pixiMap.pointNameShow) return;
      pointText.visible = true;
    };
    pose.onpointerleave = () => {
      if (pixiMap.pointNameShow) return;
      pointText.visible = false;
    };
    pose.onpointerdown = () => {
      pixiMap.clickPoint(p);
    };
    return point;
  }

  /**
   * 获取点对象
   */
  pixiMap.getPoint = (id) => {
    return pixiMap.pointContainer.getChildByName(id);
  };

  /**
   * 点位名是否常显
   * @param isShow  是或否
   */
  pixiMap.showPointName = (isShow) => {
    pixiMap.pointNameShow = isShow;
    pixiMap.pointContainer.children.forEach((item) => {
      item.children[1].visible = isShow;
    });
  };

  /**
   * 创建线
   * @param startPoint 起点坐标
   * @param endPoint 终点坐标
   * @returns {PIXI.Graphics} 线对象（pixijs的精灵）
   */
  // eslint-disable-next-line no-unused-vars
  function createLine(startPoint, endPoint) {
    const line = new PIXI.Graphics();
    return pixiMap.editLine(line, startPoint, endPoint);
  }

  /**
   * 获取线对象
   * @param id 线对象id
   */
  pixiMap.getLine = (id) => {
    return pixiMap.lineContainer.getChildByName(id);
  };

  /**
   * 编辑线
   * @param line 线对象
   * @param startPoint 起点坐标
   * @param endPoint 终点坐标
   * @param isDouble  是否双向
   */
  pixiMap.editLine = (line, startPoint, endPoint, isDouble) => {
    line.clear();
    if (isDouble) {
      //  判断是否是双向线
      line.lineStyle(
        pixiMap.lineDoubleSize,
        pixiMap.lineDoubleColor,
        pixiMap.lineDoubleAlpha
      );
    } else {
      line.lineStyle(
        pixiMap.lineSingleSize,
        pixiMap.lineSingleColor,
        pixiMap.lineSingleAlpha
      );
    }
    line.moveTo(startPoint.x, -startPoint.y);
    line.lineTo(endPoint.x, -endPoint.y);
    return line;
  };

  /**
   * 创建安全区
   * @param list 安全区数组对象
   */
  pixiMap.drawPolygon = (list) => {
    if (Array.isArray(list)) {
      list.forEach((item) => {
        pixiMap.polygonContainer.addChild(createPolygon(item));
      });
    }
  };
  /**
   * 释放安全区容器元素
   */
  pixiMap.clearPolygon = () => {
    pixiMap.polygonContainer.removeChildren();
  };

  /**
   * 创建安全区
   * @param item 安全区对象
   * @returns {Container<DisplayObject>} 返回安全区图层
   */
  function createPolygon(item) {
    // console.log(item)
    const polygon = new PIXI.Container();
    // 安全区图形
    const p = new PIXI.Graphics();
    //  安全区名称
    const polygonText = new PIXI.Text(item.name);
    polygon.addChild(p);
    polygon.addChild(polygonText);
    // 图形样式
    p.lineStyle(pixiMap.polygonSize, pixiMap.polygonColor);
    p.name = item.id + "line";
    const path = item.newPolygon;
    // console.log(path)
    let textX = 0,
      textY = 0;
    // todo
    item.polygon.forEach((t) => {
      textX += t.x;
      textY += t.y;
    });
    p.drawPolygon(path);
    //  点名称参数
    polygonText.anchor.set(0.5);
    polygonText.visible = pixiMap.polygonNameShow;
    polygonText.x = textX / item.polygon.length;
    polygonText.y = textY / item.polygon.length;
    polygonText.scale.set(0.01);
    polygon.name = item.id;
    // -----------事件分割线-------------
    polygonText.eventMode = "static";
    polygonText.onpointerdown = () => {
      pixiMap.clickPolygon(item);
    };
    return polygon;
  }

  /**
   * 创建安全区的点
   */
  pixiMap.safetyDot = (p) => {
    const dot = PIXI.Sprite.from("map/dot.png");
    dot.alpha = 0.3;
    dot.anchor.set(0.5);
    dot.tint = "0xFF0000";
    const scale = 0.1 / 44;
    dot.scale.set(scale);
    dot.x = p.x;
    dot.y = p.y;
    // -----------事件分割线-------------
    dot.eventMode = "static";
    // 为拖动时防止影响到别的点
    dot.state = false;
    return dot;
  };

  pixiMap.editPolygon = (item) => {
    return createPolygon(item);
  };

  /**
   * 是否显示安全区名字
   * @param isShow 状态
   */
  pixiMap.showPolygonName = (isShow) => {
    pixiMap.polygonNameShow = isShow;
    pixiMap.polygonContainer.children.forEach((item) => {
      item.children[1].visible = isShow;
    });
  };

  /**
   * 计算角度
   * @param orientation 角度参数
   * @returns {number} 弧度
   */
  pixiMap.toTheta = (orientation) => {
    const q0 = orientation.w;
    const q1 = orientation.x;
    const q2 = orientation.y;
    const q3 = orientation.z;
    // Canvas rotation is clock wise and in degrees
    return (
      (-Math.atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3)) *
        180.0) /
      Math.PI
    );
  };

  /**
   * 缩放
   * @param dir 正数为放大，负数为缩小
   * @param x 缩放对焦点的x坐标
   * @param y 缩放对焦点的y坐标
   */
  pixiMap.zoom = function (dir, x, y) {
    if (!x || !y) {
      x = pixiMap.div.offsetWidth / 2;
      y = pixiMap.div.offsetHeight / 2;
    }
    const center = {};
    const startShift = {};
    const startScale = {};
    center.x = x;
    center.y = y;
    startShift.x = pixiMap.stage.x;
    startShift.y = pixiMap.stage.y;
    startScale.x = pixiMap.stage.scale.x;
    startScale.y = pixiMap.stage.scale.y;
    let zoom;
    if (dir > 0) {
      zoom = 1.1;
    }
    if (dir < 0) {
      zoom = 0.9;
    }
    if (startScale.x * zoom > 140) {
      // 最大比例
      zoom = 140 / startScale.x;
    } else {
      // 最小比例分类讨论
      if (
        pixiMap.div.offsetHeight / pixiMap.div.offsetWidth >=
        pixiMap.map.height / pixiMap.map.width
      ) {
        if (
          startScale.y * zoom * pixiMap.map.height <
          pixiMap.div.offsetHeight
        ) {
          zoom = pixiMap.div.offsetHeight / pixiMap.map.height / startScale.y;
        }
      } else {
        if (startScale.x * zoom * pixiMap.map.width < pixiMap.div.offsetWidth) {
          zoom = pixiMap.div.offsetWidth / pixiMap.map.width / startScale.x;
        }
      }
    }
    pixiMap.stage.scale.set(startScale.x * zoom, startScale.y * zoom);
    pixiMap.stage.x =
      startShift.x -
      (center.x - startShift.x) * (pixiMap.stage.scale.x / startScale.x - 1);
    pixiMap.stage.y =
      startShift.y -
      (center.y - startShift.y) * (pixiMap.stage.scale.y / startScale.y - 1);
    // 防止缩放露黑边
    pixiMap.stage.x =
      pixiMap.stage.x >= pixiMap.stage.width * pixiMap.xMax
        ? pixiMap.stage.width * pixiMap.xMax
        : pixiMap.stage.x <=
          pixiMap.div.offsetWidth - pixiMap.stage.width * pixiMap.xMin
        ? pixiMap.div.offsetWidth - pixiMap.stage.width * pixiMap.xMin
        : pixiMap.stage.x;
    pixiMap.stage.y =
      pixiMap.stage.y >= pixiMap.stage.height * pixiMap.yMax
        ? pixiMap.stage.height * pixiMap.yMax
        : pixiMap.stage.y <=
          pixiMap.div.offsetHeight - pixiMap.stage.height * pixiMap.yMin
        ? pixiMap.div.offsetHeight - pixiMap.stage.height * pixiMap.yMin
        : pixiMap.stage.y;
  };

  /**
   * 对焦
   * @param pos 焦点点位
   */
  pixiMap.lookAt = (pos) => {
    pixiMap.stage.x = pixiMap.div.offsetWidth / 2;
    pixiMap.stage.y = pixiMap.div.offsetHeight / 2;
    shiftStage(pos.x, -pos.y);
  };
  /**
   * 对焦安全区
   * @param pos 焦点安全区
   */
  pixiMap.lookPolygon = (pos) => {
    pixiMap.stage.x = pixiMap.div.offsetWidth / 2;
    pixiMap.stage.y = pixiMap.div.offsetHeight / 2;
    let textX = 0,
      textY = 0;
    // 获取安全区里的中心点
    pos.polygon.forEach((t) => {
      textX += t.x;
      textY += t.y;
    });
    shiftStage(textX / pos.polygon.length, -(textY / pos.polygon.length));
  };

  /**
   * 通过缩放所需偏移来移动场景
   * @param x ros坐标系的水平偏移量
   * @param y ros坐标系的垂直偏移量
   */
  function shiftStage(x, y) {
    app.stage.x -= x * app.stage.scale.x;
    app.stage.y += y * app.stage.scale.y;
  }

  /**
   * 全局坐标转ros坐标
   * @param x 全局水平坐标
   * @param y 全局垂直坐标
   */
  pixiMap.globalToRos = (x, y) => {
    const rosX = (x - pixiMap.stage.x) / pixiMap.stage.scale.x;
    const rosY = (pixiMap.stage.y - y) / pixiMap.stage.scale.y;
    return { x: rosX, y: rosY };
  };

  /**
   * 算出开始的俩距离
   * @param a 第一个点坐标
   * @param b 第二个点坐标
   * @returns {number} 2点之间的距离
   */
  function getDistance(a, b) {
    const x = a.clientX - b.clientX;
    const y = a.clientY - b.clientY;
    return Math.hypot(x, y);
  }

  /**
   * 绘制激光雷达
   * @param list 激光线段 (将数组内的点按顺序连接，遇到参数z不为0的进行断开)
   */
  pixiMap.drawScan = (list) => {
    if (list) pixiMap.savedScan = list;
    if (!pixiMap.savedScan) return;
    // 清空容器
    pixiMap.scanContainer.removeChildren();
    let tempLine; // 缓存线段
    pixiMap.savedScan.forEach((p, index) => {
      if (tempLine) {
        // 有缓存线段
        if (p.z === 0) {
          // 如果点的z为0，则缓存线段进行连接
          tempLine.lineTo(p.x, -p.y);
          if (index === pixiMap.savedScan.length - 1) {
            // 如果连的是最后一个点，则进行渲染并清空
            pixiMap.scanContainer.addChild(tempLine);
            tempLine = null;
          }
        } else {
          // 如果点的z不为0，则将缓存线段进行渲染，并清空缓存线段
          pixiMap.scanContainer.addChild(tempLine);
          tempLine = null;
        }
      } else {
        // 没有缓存线段
        tempLine = new PIXI.Graphics(); // 创建
        tempLine.clear();
        tempLine.lineStyle(pixiMap.lineSingleSize, pixiMap.scanColor, 0.5); // 线段赋予样式
        tempLine.moveTo(p.x, -p.y); // 线段设起点
      }
    });
  };

  return pixiMap;
}
